from rest_framework.views import APIView
from rest_framework.response import Response
from django.http.response import HttpResponse
import re
from myapp.models import *
from utils.myjwt import myjwt
from utils.myredis import r
from utils.db import db
from datetime import datetime

from captcha.image import ImageCaptcha
import random
import string
from myapp.sms import send_message
from django.contrib.auth.hashers import make_password, check_password
import time
import requests
import json

#图片验证码
class ImageCodeView(APIView):
    def get(self,request,uuid):
        code = ''.join(random.sample(string.ascii_letters+string.ascii_letters,5))
        print('code',code)
        #生成图片验证码
        img = ImageCaptcha()
        image = img.generate(code)

        rds = r.set_str(uuid,code,60)
        if not rds:
            return Response({"code": 500, 'msg': '验证码缓存失败'})

        return HttpResponse(image,content_type='image/png')

#短信验证码
class CodeView(APIView):
    def get(self, request):
        mobile = request.query_params.get('mobile')
        if not mobile:
            return Response({"code": 400, 'msg': '手机号不存在'})

        if not re.findall(r"^1[3-9]\d{9}$", mobile):
            return Response({"code":404, 'msg':"手机号格式不正确"})

        code = ''.join(random.sample(string.ascii_letters + string.digits,5))

        if not code:
            return Response({"code": 500, 'msg': "验证码未生成"})

        num = send_message(mobile,code)
        if num:
            rds = r.set_str(mobile,code,60)
            if not rds:
                return Response({"code": 500, 'msg': '验证码缓存失败'})

            return Response({"code": 200, 'msg': '验证码发送成功'})
        else:
            return Response({"code": 500, 'msg': '验证码发送失败'})

#注册
class RegisterView(APIView):
    def get(self,request):
        mobile = request.query_params.get('mobile')
        password = request.query_params.get('password')
        uuid = request.query_params.get('uuid')
        code = request.query_params.get('code')
        num = request.query_params.get('num')
        print(mobile,password,uuid,num,code)

        if not all({mobile,password,uuid,code,num}):
            return Response({"code": 400, 'msg': '数据传输不完整'})

        if not re.findall(r"^1[3-9]\d{9}$",mobile):
            return Response({"code": 400, 'msg': '手机号格式不正确'})

        #从redis中获取code进行对比
        code1 = r.get_str(uuid)
        if not code1:
            return Response({"code": 400, 'msg': '验证码已过期'})
        if code1 != code:
            return Response({"code": 400, 'msg': '验证码输入有误'})

        user_info = UserModel.objects.filter(mobile=mobile)
        if user_info:
            return Response({"code": 400, 'msg': '该手机号已注册'})

        try:
            username = '用户' + str(mobile[-4:])
            if not username:
                return Response({"code": 500, 'msg': '用户名生成失败'})

            #添加用户
            new_user = UserModel.objects.create(username=username,mobile=mobile,password=make_password(password),user_type=int(num))
            new_user.save()
            return Response({"code": 200, 'msg': '注册成功'})

        except Exception as e:
            print('错误原因',e)
            return Response({"code": 500, 'msg': '注册失败'})

#装饰器
def check_login(func):
    def wrapper(self,request,*args,**kwargs):
        token = request.headers.get('token')

        #判断redis中token是否存在
        is_exists = r.exists_str(token)
        #代表token被禁用
        if is_exists:
            return Response({
                'code': 401,
                'msg': '用户未登录'
            })
        payload = myjwt.jwt_de(token)
        #如果token过期
        if payload == 403:
            return Response({
                'code': 403,
            })
        if payload:
            request.user_id = payload.get('user_id')
        else:
            return Response({
                'code': 400,
                'msg': '用户未登录'
            })
        return func(self,request,*args,**kwargs)
    return wrapper


#登录
class LoginView(APIView):
    def post(self,request):
        mobile = request.data.get('mobile')
        password = request.data.get('password')
        if not all([mobile,password]):
            return Response({"code": 400, 'msg': '数据传输不完整'})

        if not re.findall(r"^1[3-9]\d{9}$", mobile):
            return Response({"code": 400, 'msg': '手机号格式不正确'})

        try:
            user = UserModel.objects.filter(mobile=mobile).first()
            #密码校验
            if check_password(password,user.password):
                time1 = int(time.time()) + 3600
                payload1 = {
                    'user_id':user.id,
                    'mobile':user.mobile,
                    'exp':time1
                }

                time2 = int(time.time()) + 3600*24*7
                payload2 = {
                    'user_id':user.id,
                    'mobile':user.mobile,
                    'exp':time2
                }

                token = myjwt.jwt_en(payload1)
                retoken = myjwt.jwt_en(payload2)

                #将用户个人信息进行缓存
                dict1 = {
                    'user_id': user.id,
                    'mobile': user.mobile,
                    'account': float(user.account),
                    'user_card': user.user_card,
                    'user_type': user.user_type,
                }

                if not dict1:
                    return Response({"code": 500, 'msg': '添加字典失败'})

                # 将用户个人信息缓存到hash里
                for key, value in dict1.items():
                    r.insert_hash(str(user.id), key, value)

                return Response({
                    'code':200,
                    'msg':'登录成功',
                    'token':token,
                    'retoken': retoken,
                })

            else:
                return Response({"code": 400, 'msg': '密码错误'})

        except Exception as e:
            print('错误原因为', e)
            return Response({"code": 500, 'msg': '登录失败'})

    @check_login
    def delete(self,request):
        token = request.headers.get('token')
        #将要清楚的token存入到redis缓存中
        r.set_str(token,1,7200)
        return Response({"code": 200, 'msg': '退出登录成功'})

from requests_oauthlib import OAuth1Session
from django.shortcuts import redirect
from django.urls import reverse

#微博路由
class WeiBoView(APIView):
    def get(self,request):
        client_id = "3674019597"
        # 回调地址
        redirect_uri = "http://127.0.0.1:8000/user/weiboCallback"
        url = "https://api.weibo.com/oauth2/authorize?client_id=%s&redirect_uri=%s&response_type=code" % (
            client_id, redirect_uri)
        return Response({"code": 200, 'msg': url})

#微博回调
class WeiboCallbackView(APIView):
    def get(self,request):
        code = self.request.query_params.get('code')
        if not code:
            return Response({"code": 200, 'msg': '接收code失败'})
        #设置向access_token接口访问的data里的数据
        data = {
            'client_id': "3674019597", 'client_secret': '7ae99bc0d54ead29fc8d1b9fabd78587',
            "grant_type": "authorization_code",
            'redirect_uri': 'http://127.0.0.1:8000/user/weiboCallback', 'code': code
        }

        #发起post请求
        res = requests.post('https://api.weibo.com/oauth2/access_token',data=data)

        #获取微博上的用户信息
        mes = json.loads(res.text)
        access_token = mes['access_token']
        uid = mes['uid']

        #查询表中用户是否存在
        sql = """select user_id from third_user inner join user on third_user.user_id = user.id where third_user.uid = %s"""%(str(uid))
        user = db.findOne(sql)

        #如果用户存在，生成jwt并返回jwt_token
        if user:
            time1 = int(time.time()) + 3600
            payload1 = {
                'user_id': user.id,
                'mobile': user.mobile,
                'exp': time1
            }

            time2 = int(time.time()) + 3600 * 24 * 7
            payload2 = {
                'user_id': user.id,
                'mobile': user.mobile,
                'exp': time2
            }
            token = myjwt.jwt_en(payload1)
            retoken = myjwt.jwt_en(payload2)

            url = 'http://localhost:8080/third?token='+token +'&retoken='+retoken
            params = {
                'access_token':access_token,
                'uid':uid
            }
            response = requests.get(url,params=params)

            return response.json()
        else:
            #进行手机号绑定
            responses = 'http://localhost:8080/bind?access_token='+access_token+'&uid='+uid
            return responses.json()

#微博登录
class ThirdLoginView(APIView):
    def post(self,request):
        mobile = request.data.get('mobile')
        password = request.data.get('password')
        user_type = request.data.get('type')
        access_token = request.data.get('access_token')
        uid = request.data.get('uid')
        url = request.data.get('url')

        if not all([mobile,access_token,uid,url]):
            return Response({"code": 400, 'msg': '接收失败'})

        user_info = UserModel.objects.filter(mobile=mobile).first()
        if user_info:
            return Response({"code": 400, 'msg': '该用户已存在'})

        username = '用户' + str(mobile[-4:])
        new_user = UserModel.objects.create(username=username,mobile=mobile,password=make_password(password),user_type=user_type)
        new_user.save()

        sql = """select id,mobile from user where mobile=%s"""%(mobile)
        res = db.findOne(sql)

        third = ThirdUserModel.objects.create(user_id=res['id'],token=access_token,uid=uid,url=url)
        third.save()

        time1 = int(time.time()) + 3600
        payload1 = {
            'user_id': res['id'],
            'mobile': res['mobile'],
            'exp': time1
        }

        time2 = int(time.time()) + 3600 * 24 * 7
        payload2 = {
            'user_id': res['id'],
            'mobile': res['mobile'],
            'exp': time2
        }
        token = myjwt.jwt_en(payload1)
        retoken = myjwt.jwt_en(payload2)

        return Response({
            'code':200,
            'msg':'登录成功',
            'token':token,
            'retoken':retoken
        })


#刷新token
class ReTokenView(APIView):
    def post(self,request):
        retoken = request.data.get('retoken')
        if not retoken:
            return Response({"code": 400, 'msg': 'retoken接收失败'})
        payload = myjwt.jwt_de(retoken)

        time1 = payload['exp']
        if time1 < int(time1):
            return Response({"code": 400, 'msg': 'retoken已过期'})
        else:
            time1 = int(time1) + 3600
            payload1 = {
                'user_id': payload['user_id'],
                'mobile': payload['mobile'],
                'exp': time1
            }
            token = myjwt.jwt_en(payload1)

            return Response({
                'code': 202,
                'token': token,
            })


#获取用户个人信息
class UserInfoView(APIView):
    @check_login
    def get(self,request):
        user_id = request.user_id
        if not user_id:
            return Response({"code": 500, 'msg': '获取失败'})

        temp = r.get_all_hash(str(user_id))

        try:
            return Response({"code": 200, 'data':temp})
        except:
            return Response({"code": 500, 'msg': '失败'})


#专业标签
class ProfessionView(APIView):
    def get(self,request):
        lst = 'biaoqian'
        rds = r.list_getAll(lst,0,-1)
        print(rds,type(rds))
        if not rds:
            return Response({"code": 500, 'msg': '获取失败'})

        return Response({"code": 200, 'msg': '获取成功','data':rds})

    def post(self,request):
        name = request.data.get('name')
        if not all(name):
            return Response({"code": 400, 'msg': '传输失败'})

        old_name = ProfessionModel.objects.filter(profession_name=name).first()
        if old_name:
            return Response({"code": 400, 'msg': '已经添加过'})

        num = ProfessionModel.objects.create(profession_name=name)
        if not num:
            return Response({"code": 500, 'msg': '添加失败'})

        lst = 'biaoqian'
        try:
            r.list_push(lst,name)
            return Response({"code": 500, 'msg': '添加成功'})

        except Exception as e:
            print('错误',e)
            return Response({"code": 500, 'msg': '添加失败'})

class ShopView(APIView):
    @check_login
    def post(self,request):
        user_id = request.user_id
        shop_name = request.data.get('shop_name')

        shop_user = SchoolModel.objects.create(user_id=user_id,shop_name=shop_name)
        shop_user.save()
        return Response({
            'code':200,
            'msg':'添加成功'
        })


class GoodsView(APIView):
    @check_login
    def get(self,request):
        user_id = request.user_id
        sql = """select id from shop where user_id = %d"""%(int(user_id))
        res = db.findAll(sql)
        for i in res:
            goods = GoodsModel.objects.filter(shop_id=int(i['id'])).all()

            temp = []
            for j in goods:

                temp.append({
                    'user_id': j.user_id,
                    'price': j.price,
                    'goods_introduce': j.goods_introduce,
                    'profession_id': j.profession_id,
                    'shop_id': j.shop_id,
                })
            return Response({
                'code': 200,
                'msg': '获取成功',
                'data':temp
            })

    @check_login
    def post(self,request):
        user_id = request.user_id
        shop_id = request.data.get('shop_id')
        profession_id = request.data.get('profession_id')
        goods_name = request.data.get('goods_name')
        price = float(request.data.get('price'))
        goods_introduce = request.data.get('goods_introduce')

        if not all({user_id,shop_id,profession_id,goods_name,price,goods_introduce}):
            return Response({
                'code': 400,
                'msg': '接收数据不完整'
            })

        goods_info = GoodsModel.objects.create(user_id=user_id,shop_id=shop_id,profession_id=profession_id,goods_name=goods_name,price=price,goods_introduce=goods_introduce)
        goods_info.save()

        return Response({
            'code': 200,
            'msg': '添加完成'
        })

#购物车
class ShoppingCartView(APIView):
    @check_login
    def get(self, request):
        user_id = request.user_id
        try:
            shopping = ShoppingCartModel.objects.filter(user_id=user_id).all()
            temp = []
            for j in shopping:
                temp.append({
                    'user_id': j.user_id,
                    'goods_id': j.goods_id,
                    'goods_count': j.goods_count,
                    'goods_price': j.goods_price,
                })
            return Response({
                'code': 200,
                'msg': '获取成功',
                'data': temp
            })

        except Exception as e:
            print('错误为',e)
            return Response({
                'code': 500,
                'msg': '获取失败'
            })

    @check_login
    def post(self,request):
        user_id = request.user_id
        shop_id = self.request.data.get('shop_id')
        goods_id = self.request.data.get('goods_id')
        goods_count = self.request.data.get('goods_count')
        goods_price = self.request.data.get('goods_price')

        if not all({user_id,shop_id,goods_id,goods_count}):
            return Response({
                'code': 400,
                'msg': '接收数据不完整'
            })

        try:
            shopping = ShoppingCartModel.objects.create(user_id=user_id,shop_id=shop_id,goods_id=goods_id,goods_count=goods_count,goods_price=goods_price)
            shopping.save()
            return Response({
                'code': 200,
                'msg': '添加购物车成功'
            })
        except Exception as e:
            print('错误为',e)
            return Response({
                'code': 500,
                'msg': '添加购物车失败'
            })

    @check_login
    def delete(self,request):
        user_id = request.user_id
        shop_id = self.request.data.get('shop_id')
        goods_id = self.request.data.get('goods_id')

        ShoppingCartModel.objects.filter(user_id=user_id,shop_id=shop_id,goods_id=goods_id).delete()
        return Response({"code": 200, 'msg': '删除成功'})

#订单
class OrderView(APIView):
    @check_login
    def post(self,request):
        pass